﻿using System;
using System.Collections;
using System.Collections.Generic;

namespace Core.Tools
{
    /// <summary>
    /// 参数字典的初始化配置
    /// </summary>
    public enum ParamsDictionaryOption
    {
        /// <summary>
        /// 默认值，无配置
        /// </summary>
        None = 0x0,
        /// <summary>
        /// 允许 Null Key
        /// </summary>
        AllowNullKey = 0x1,
        /// <summary>
        /// 允许 Key 重复
        /// </summary>
        AllowRepeat = 0x2
    }

    /// <summary>
    /// 参数字典
    /// </summary>
    /// <typeparam name="TKey">字典 Key 的类型</typeparam>
    /// <typeparam name="TValue">字典 Value 的类型</typeparam>
    [Serializable]
    public class ParamsDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>, IDictionary<TKey, TValue>, IDictionary
    {
        private const int InitializeSize = 3; // 初始数组大小
        private const int UnUsedHashCode = -1; // 未使用的实体 HashCode
        private const int FreedHashCode = -2; // 移除的实体 HashCode

        private int[] InternalBuckets; // Hash 值与元素索引的映射 -1 表示未使用
        private Entity[] InternalEntries; // 元素集合 无序
        private int InternalCount; // 已保存元素数量
        private int InternalFreed; // 已释放的空间 Index。 -1 表示无

        private ParamsDictionaryOption InternalOption;

        private IEqualityComparer<TKey> KeyComparer;

        /// <summary>
        /// 字典中保存的元素
        /// </summary>
        [Serializable]
        private struct Entity
        {
            public int HashCode; // Key 的 Hash 值 -1 表示未使用 -2表示已释放
            public int Next; // 与该 Hash 值相同的其他元素的索引
            public TKey Key; // 键
            public TValue Value; // 值
        }


        /// <summary>
        /// 使用默认参数初始化字典
        /// </summary>
        public ParamsDictionary()
        {
            KeyComparer = EqualityComparer<TKey>.Default;

            InternalFreed = -1;
            Resize(InitializeSize);
        }

        /// <summary>
        /// 使用默认参数初始化字典，并指定初始字典容量
        /// </summary>
        /// <param name="Size">初始容量</param>
        public ParamsDictionary(int Size)
        {
            KeyComparer = EqualityComparer<TKey>.Default;

            InternalFreed = -1;
            Resize(Size);
        }

        public int Count
        {
            get { return InternalCount; }
        }

        /// <summary>
        /// 指定字典配置参数和初始容量初始化字典
        /// </summary>
        /// <param name="Size">初始容量</param>
        /// <param name="Option">配置参数</param>
        public ParamsDictionary(int Size, ParamsDictionaryOption Option)
            : this(Size)
        {
            InternalOption = Option;
        }

        /// <summary>
        /// 使用默认初始容量和指定配置参数初始字典
        /// </summary>
        /// <param name="Option">配置参数</param>
        public ParamsDictionary(ParamsDictionaryOption Option)
            : this()
        {
            InternalOption = Option;
        }

        /// <summary>
        /// 获得指定键的哈希值，如果该键为空，并且允许配置允许空键，则返回 0;不允许空值则发生异常。
        /// </summary>
        /// <param name="Key">需要获取哈希值得键对象</param>
        /// <returns></returns>
        private int GetHashCode(TKey Key)
        {
            if (Key == null)
            {
                if ((InternalOption & ParamsDictionaryOption.AllowNullKey) == 0)
                {
                    throw new Exception("不允许 Null 键");
                }

                return 0;
            }

            return KeyComparer.GetHashCode(Key) & int.MaxValue;
        }

        private bool EqualKey(TKey Before, TKey After)
        {
            if (Before == null)
            {
                return After == null;
            }

            return KeyComparer.Equals(Before, After);
        }

        public TValue this[TKey Key]
        {
            get
            {
                int hashCode = GetHashCode(Key);
                int last, i = LastEntry(Key, out last, hashCode);
                if (i >= 0)
                {
                    return InternalEntries[i].Value;
                }
                throw new Exception("不存在键 -- " + Key);
            }
            set
            {
                Insert(Key, value, false);
            }
        }

        public KeyValuePair<TKey, TValue> this[int Index]
        {
            get
            {
                if (Index >= 0 && Index < InternalCount)
                {
                    if (InternalFreed != -1)
                    {
                        Defragment();

                        ReBuckets();
                    }

                    return new KeyValuePair<TKey, TValue>(InternalEntries[Index].Key, InternalEntries[Index].Value);
                }

                throw new IndexOutOfRangeException("Index");
            }
        }

        public bool TryGetValue(TKey key, out TValue value)
        {
            int hashCode = GetHashCode(key);
            int last, i = LastEntry(key, out last, hashCode);
            if (i >= 0)
            {
                value = InternalEntries[i].Value;
                return true;
            }
            value = default(TValue);
            return false;
        }

        private int FirstEntry(TKey key, out int last, int hashCode)
        {
            last = -1;
            if (InternalCount != 0)
            {
                bool isFind = false;
                int index = -1;
                for (int i = InternalBuckets[hashCode % InternalBuckets.Length]; i >= 0; last = index, index = i, i = InternalEntries[i].Next)
                {
                    if (InternalEntries[i].HashCode == hashCode && EqualKey(InternalEntries[i].Key, key))
                    {
                        isFind = true;
                    }
                    else if (isFind)
                    {
                        return index;
                    }
                }
                if (isFind)
                {
                    return index;
                }
            }
            return -1;
        }

        private int LastEntry(TKey key, out int last, int hashCode)
        {
            last = -1;
            if (InternalCount != 0)
            {
                for (int i = InternalBuckets[hashCode % InternalBuckets.Length]; i >= 0; last = i, i = InternalEntries[i].Next)
                {
                    if (InternalEntries[i].HashCode == hashCode && EqualKey(key, InternalEntries[i].Key))
                    {
                        return i;
                    }
                }
            }
            return -1;
        }

        private void Insert(TKey key, TValue value, bool add)
        {
            if (add && InternalFreed == -1 && InternalCount == InternalEntries.Length)
            {
                Resize();
            }

            int hashCode = GetHashCode(key);

            int targetBucket = hashCode % InternalBuckets.Length;

            int last = -1;

            int similar = -1;

            for (int i = InternalBuckets[targetBucket]; i >= 0; last = i, i = InternalEntries[i].Next)
            {
                if (InternalEntries[i].HashCode == hashCode && EqualKey(InternalEntries[i].Key, key))
                {
                    if (add)
                    {
                        if ((InternalOption & ParamsDictionaryOption.AllowRepeat) == 0)
                        {
                            throw new Exception("不允许重复键 -- " + key);
                        }
                        similar = i;
                        break;
                    }
                    else
                    {
                        InternalEntries[i].Value = value;
                        return;
                    }
                }
            }

            int index;
            if (InternalFreed != -1)
            {
                index = InternalFreed;
                InternalFreed = InternalEntries[InternalFreed].Next;
            }
            else
            {
                if (!add && InternalCount == InternalEntries.Length)
                {
                    Resize();
                    targetBucket = hashCode % InternalEntries.Length;
                }
                index = InternalCount;
            }
            InternalEntries[index].HashCode = hashCode;
            InternalEntries[index].Key = key;
            InternalEntries[index].Value = value;
            if (similar < 0)
            {
                InternalEntries[index].Next = InternalBuckets[targetBucket];
                InternalBuckets[targetBucket] = index;
            }
            else if (last < 0)
            {
                InternalEntries[index].Next = similar;
                InternalBuckets[targetBucket] = index;
            }
            else
            {
                InternalEntries[last].Next = index;
                InternalEntries[index].Next = similar;
            }

            ++InternalCount;
        }

        public bool RemoveLast(TKey key)
        {
            int hashCode = GetHashCode(key);
            int bucket = hashCode % InternalBuckets.Length;
            int last, i = LastEntry(key, out last, hashCode);
            if (i != -1)
            {
                if (last < 0)
                {
                    InternalBuckets[bucket] = InternalEntries[i].Next;
                }
                else
                {
                    InternalEntries[last].Next = InternalEntries[i].Next;
                }

                InternalEntries[i].HashCode = FreedHashCode;
                InternalEntries[i].Next = InternalFreed;
                InternalEntries[i].Key = default(TKey);
                InternalEntries[i].Value = default(TValue);
                InternalFreed = i;

                --InternalCount;

                return true;
            }
            return false;
        }

        public bool RemoveFirst(TKey key)
        {
            int hashCode = GetHashCode(key);
            int bucket = hashCode % InternalBuckets.Length;
            int last, i = FirstEntry(key, out last, hashCode);
            if (i != -1)
            {
                if (last < 0)
                {
                    InternalBuckets[bucket] = InternalEntries[i].Next;
                }
                else
                {
                    InternalEntries[last].Next = InternalEntries[i].Next;
                }

                InternalEntries[i].HashCode = FreedHashCode;
                InternalEntries[i].Next = InternalFreed;
                InternalEntries[i].Key = default(TKey);
                InternalEntries[i].Value = default(TValue);
                InternalFreed = i;

                --InternalCount;

                return true;
            }
            return false;
        }

        public bool RemoveAll(TKey key)
        {
            if (InternalCount != 0)
            {
                int hashCode = GetHashCode(key);
                int bucket = hashCode % InternalBuckets.Length;
                int last = -1;
                int next = -1;
                bool isFind = false;
                for (int i = InternalBuckets[bucket]; i >= 0; i = next)
                {
                    next = InternalEntries[i].Next;
                    if (InternalEntries[i].HashCode == hashCode && EqualKey(InternalEntries[i].Key, key))
                    {
                        isFind = true;
                        InternalEntries[i].HashCode = FreedHashCode;
                        InternalEntries[i].Next = InternalFreed;
                        InternalEntries[i].Key = default(TKey);
                        InternalEntries[i].Value = default(TValue);
                        InternalFreed = i;

                        --InternalCount;
                    }
                    else if (isFind)
                    {
                        last = i;
                    }
                    else
                    {
                        break;
                    }
                }
                if (isFind)
                {
                    if (last < 0)
                    {
                        InternalBuckets[bucket] = next;
                    }
                    else
                    {
                        InternalEntries[last].Next = next;
                    }
                    return true;
                }
            }
            return false;
        }

        public int FindFirstIndex(TKey key)
        {
            int hashCode = GetHashCode(key);
            int last, i = FirstEntry(key, out last, hashCode);
            return i;
        }

        public int FindLastIndex(TKey key)
        {
            int hashCode = GetHashCode(key);
            int last, i = LastEntry(key, out last, hashCode);
            return i;
        }

        private void Resize()
        {
            int newSize = InternalCount * 2;

            unchecked
            {
                if ((uint)newSize > ArrayHelper.MaxPrimeArrayLength && ArrayHelper.MaxPrimeArrayLength > InternalCount)
                {
                    Resize(ArrayHelper.MaxPrimeArrayLength);
                }
                else
                {
                    Resize(ArrayHelper.GetPrime(newSize));
                }
            }
        }

        private void Resize(int NewSize)
        {
            int[] NewBuckets = new int[NewSize];
            for (int i = 0; i < NewBuckets.Length; i++)
            {
                NewBuckets[i] = -1;
            }


            Entity[] newEntries = InternalEntries;
            Array.Resize(ref newEntries, NewSize);

            int Count = Math.Min(InternalEntries == null ? 0 : InternalEntries.Length, NewSize);
            int Index = 0;

            for (int i = 0; i < Count; i++)
            {
                switch (newEntries[i].HashCode)
                {
                    case UnUsedHashCode:
                        goto Return;
                    case FreedHashCode:
                        break;
                    default:
                        if (Index != i)
                        {
                            newEntries[Index] = newEntries[i];
                        }

                        int bucket = newEntries[Index].HashCode % NewSize;
                        newEntries[Index].Next = NewBuckets[bucket];
                        NewBuckets[bucket] = Index;

                        ++Index;
                        break;
                }
            }

            Return:
            for (; Index < NewSize; Index++)
            {
                newEntries[Index].HashCode = UnUsedHashCode;
            }

            InternalBuckets = NewBuckets;
            InternalEntries = newEntries;
            InternalFreed = -1;
        }

        private void Defragment()
        {
            InternalFreed = -1;

            for (int i = 0, j = 0; i < InternalEntries.Length; i++)
            {
                switch (InternalEntries[i].HashCode)
                {
                    case UnUsedHashCode:
                        return;
                    case FreedHashCode:
                        break;
                    default:
                        if (j != i)
                        {
                            InternalEntries[j] = InternalEntries[i];
                        }
                        ++j;
                        break;
                }
            }
        }

        private void ReBuckets()
        {
            for (int i = 0; i < InternalCount; i++)
            {
                if (InternalEntries[i].HashCode >= 0)
                {
                    int bucket = InternalEntries[i].HashCode % InternalBuckets.Length;
                    InternalEntries[i].Next = InternalBuckets[bucket];
                    InternalBuckets[bucket] = i;
                }
            }
        }

        public void Fixed()
        {
            Defragment();
            Resize(InternalCount);
        }

        public void Sort(IComparer<KeyValuePair<TKey, TValue>> Comparer)
        {
            Defragment();

            Array.Sort(InternalEntries, 0, InternalCount, new ComparerSort(Comparer));

            ReBuckets();
        }

        public void Sort(Comparison<KeyValuePair<TKey, TValue>> Comparer)
        {
            Defragment();

            Array.Sort(InternalEntries, 0, InternalCount, new ComparisonSort(Comparer));

            ReBuckets();
        }

        public void Add(TKey key, TValue value)
        {
            Insert(key, value, true);
        }

        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
        {
            return new Enumerator(this);
        }

        public ValuesCollection GetValues(TKey Key)
        {
            return new ValuesCollection(this, Key);
        }

        /// <summary>
        /// 遍历字典元素
        /// </summary>
        /// <param name="Key">指定 Key。</param>
        /// <param name="Function">回掉函数，当此回掉函数返回 true 时则继续遍历，返回 false 则停止。</param>
        /// <returns>如果是因为回掉函数返回 false 而终止遍历的返回该元素的索引，否则返回 -1</returns>
        public int Each(TKey Key, Func<TValue, bool> Function)
        {
            int HashCode = GetHashCode(Key);

            for (int i = InternalBuckets[HashCode % InternalBuckets.Length]; i != -1; i = InternalEntries[i].Next)
            {
                if (InternalEntries[i].HashCode == HashCode && EqualKey(Key, InternalEntries[i].Key))
                {
                    if (!Function(InternalEntries[i].Value))
                    {
                        return i;
                    }
                }
            }

            return -1;
        }

        /// <summary>
        /// 遍历字典元素
        /// </summary>
        /// <param name="Function">回掉函数，当此回掉函数返回 true 时则继续遍历，返回 false 则停止。</param>
        /// <returns>如果是因为回掉函数返回 false 而终止遍历的返回该元素的索引，否则返回 -1</returns>
        public int Each(Func<TKey, TValue, bool> Function)
        {
            for (int i = 0; i < InternalEntries.Length; i++)
            {
                if (InternalEntries[i].HashCode == UnUsedHashCode)
                {
                    break;
                }
                else if (InternalEntries[i].HashCode != FreedHashCode && !Function(InternalEntries[i].Key, InternalEntries[i].Value))
                {
                    return i;
                }
            }

            return -1;
        }

        public void Clear()
        {
            if (InternalCount > 0)
            {
                for (int i = 0; i < InternalBuckets.Length; i++) InternalBuckets[i] = -1;
                Array.Clear(InternalEntries, 0, InternalCount);
                InternalFreed = -1;
                InternalCount = 0;
            }
        }

        public bool ContainsKey(TKey Key)
        {
            int hashCode = GetHashCode(Key);
            int last, i = LastEntry(Key, out last, hashCode);
            return i >= 0;
        }

        public ICollection<TKey> Keys
        {
            get
            {
                return new AgentEnumerable<KeyValuePair<TKey, TValue>, TKey>(this, (Entity) => { return Entity.Key; }, InternalCount);
            }
        }

        public ICollection<TValue> Values
        {
            get
            {
                return new AgentEnumerable<KeyValuePair<TKey, TValue>, TValue>(this, (Entity) => { return Entity.Value; }, InternalCount);
            }
        }

        bool IDictionary<TKey, TValue>.Remove(TKey Key)
        {
            return RemoveAll(Key);
        }

        void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> Item)
        {
            Add(Item.Key, Item.Value);
        }

        bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> Item)
        {
            var ValueComparer = EqualityComparer<TValue>.Default;

            return Each(Item.Key, (Value) =>
            {
                return !ValueComparer.Equals(Value, Item.Value);

            }) != -1;
        }

        public void CopyTo(KeyValuePair<TKey, TValue>[] Array, int ArrayIndex)
        {
            if (Array == null)
            {
                throw new NullReferenceException("Array");
            }

            if (Array.Rank != 0)
            {
                throw new ArgumentException("Rank");
            }

            if (ArrayIndex < 0 || ArrayIndex >= Array.Length)
            {
                throw new IndexOutOfRangeException("ArrayIndex");
            }

            if (Array.Length - ArrayIndex < InternalCount)
            {
                throw new IndexOutOfRangeException("ArrayIndex");
            }

            Each((Key, Value) =>
            {
                Array[ArrayIndex] = new KeyValuePair<TKey, TValue>(Key, Value);

                ++ArrayIndex;

                return true;
            });
        }

        bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> Item)
        {
            var ValueComparer = EqualityComparer<TValue>.Default;

            int HashCode = GetHashCode(Item.Key);

            for (int i = InternalBuckets[HashCode % InternalBuckets.Length], LastIndex = -1; i != -1; LastIndex = i, i = InternalEntries[i].Next)
            {
                if (InternalEntries[i].HashCode == HashCode && EqualKey(Item.Key, InternalEntries[i].Key) && ValueComparer.Equals(Item.Value, InternalEntries[i].Value))
                {
                    int TargetBucket = HashCode % InternalBuckets.Length;

                    if (LastIndex == -1)
                    {
                        InternalBuckets[TargetBucket] = InternalEntries[i].Next;
                    }
                    else
                    {
                        InternalEntries[LastIndex].Next = InternalEntries[i].Next;
                    }

                    InternalEntries[i].HashCode = FreedHashCode;
                    InternalEntries[i].Next = InternalFreed;
                    InternalEntries[i].Key = default(TKey);
                    InternalEntries[i].Value = default(TValue);
                    InternalFreed = i;

                    --InternalCount;

                    return true;
                }
            }

            return false;
        }

        bool IDictionary.Contains(object Key)
        {
            return ContainsKey((TKey)Key);
        }

        void IDictionary.Add(object Key, object Value)
        {
            Add((TKey)Key, (TValue)Value);
        }

        void IDictionary.Clear()
        {
            Clear();
        }

        IDictionaryEnumerator IDictionary.GetEnumerator()
        {
            return new Enumerator(this);
        }

        void IDictionary.Remove(object Key)
        {
            RemoveAll((TKey)Key);
        }

        void ICollection.CopyTo(Array Array, int Index)
        {
            if (Array == null)
            {
                throw new NullReferenceException("Array");
            }

            if (Array.Rank != 0)
            {
                throw new ArgumentException("Rank");
            }

            if (Index < 0 || Index >= Array.Length)
            {
                throw new IndexOutOfRangeException("Index");
            }

            if (Array.Length - Index < InternalCount)
            {
                throw new IndexOutOfRangeException("Index");
            }

            if (Array is KeyValuePair<TKey, TValue>[])
            {
                CopyTo((KeyValuePair<TKey, TValue>[])Array, Index);
            }
            else if (Array is DictionaryEntry[])
            {
                var EntryArray = (DictionaryEntry[])Array;

                var Enumerator = (IDictionaryEnumerator)new Enumerator(this);

                while (Enumerator.MoveNext())
                {
                    EntryArray[Index] = Enumerator.Entry;

                    ++Index;
                }
            }
            else
            {
                object[] Objects = Array as object[];

                if (Objects == null)
                {
                    throw new ArgumentException("InvalidArrayType");
                }

                Each((Key, Value) =>
                {
                    Objects[Index] = new KeyValuePair<TKey, TValue>(Key, Value);

                    ++Index;

                    return true;
                });
            }
        }

        ICollection IDictionary.Keys
        {
            get
            {
                return new AgentEnumerable<KeyValuePair<TKey, TValue>, TKey>(this, (Entity) => { return Entity.Key; }, InternalCount);
            }
        }

        ICollection IDictionary.Values
        {
            get
            {
                return new AgentEnumerable<KeyValuePair<TKey, TValue>, TValue>(this, (Entity) => { return Entity.Value; }, InternalCount);
            }
        }

        bool IDictionary.IsReadOnly
        {
            get
            {
                return false;
            }
        }

        bool IDictionary.IsFixedSize
        {
            get
            {
                return false;
            }
        }

        int ICollection.Count
        {
            get
            {
                return InternalCount;
            }
        }

        object ICollection.SyncRoot
        {
            get
            {
                return null;
            }
        }

        bool ICollection.IsSynchronized
        {
            get
            {
                return false;
            }
        }

        bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly
        {
            get
            {
                return false;
            }
        }

        object IDictionary.this[object Key]
        {
            get
            {
                return this[(TKey)Key];
            }
            set
            {
                this[(TKey)Key] = (TValue)value;
            }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public sealed class ValuesCollection : IEnumerable<TValue>
        {
            private ParamsDictionary<TKey, TValue> InternalContent;
            private int InternalHashCode;
            private TKey InternalKey;
            private int InternalLength;

            internal ValuesCollection(ParamsDictionary<TKey, TValue> Content, TKey Key)
            {
                InternalContent = Content;
                InternalKey = Key;
                InternalHashCode = Content.GetHashCode(Key);
                InternalLength = -1;
            }

            public int Length
            {
                get
                {
                    if (InternalLength == -1)
                    {
                        var Enumerator = GetEnumerator();

                        InternalLength = 0;

                        while (Enumerator.MoveNext())
                        {
                            ++InternalLength;
                        }
                    }

                    return InternalLength;
                }
            }

            public IEnumerator<TValue> GetEnumerator()
            {
                return new Enumerator(this);
            }

            public TValue[] ToArray()
            {
                TValue[] Result = new TValue[Length];

                var Enumerator = GetEnumerator();

                for (int i = 0; i < Result.Length; i++)
                {
                    Enumerator.MoveNext();
                    Result[i] = Enumerator.Current;
                }

                return Result;
            }

            IEnumerator IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }

            private sealed class Enumerator : IEnumerator<TValue>
            {
                public Enumerator(ValuesCollection Values)
                {
                    InternalContent = Values.InternalContent;
                    InternalHashCode = Values.InternalHashCode;
                    InternalKey = Values.InternalKey;

                    InternalIndex = -1;
                }

                private readonly ParamsDictionary<TKey, TValue> InternalContent;
                private readonly int InternalHashCode;
                private readonly TKey InternalKey;

                private int InternalIndex;

                public TValue Current
                {

                    get
                    {
                        return InternalContent.InternalEntries[InternalIndex].Value;
                    }
                }

                object IEnumerator.Current { get { return Current; } }

                public void Dispose()
                {
                }

                public bool MoveNext()
                {
                    var Entries = InternalContent.InternalEntries;

                    if (InternalIndex == -1)
                    {
                        var Buckets = InternalContent.InternalBuckets;

                        for (InternalIndex = Buckets[InternalHashCode % Buckets.Length]; InternalIndex >= 0; InternalIndex = Entries[InternalIndex].Next)
                        {
                            if (Entries[InternalIndex].HashCode == InternalHashCode && InternalContent.EqualKey(InternalKey, Entries[InternalIndex].Key))
                            {
                                return true;
                            }
                        }
                    }
                    else
                    {
                        InternalIndex = InternalContent.InternalEntries[InternalIndex].Next;
                    }

                    if (InternalIndex == -1)
                    {
                        return false;
                    }

                    if (Entries[InternalIndex].HashCode == InternalHashCode && InternalContent.EqualKey(InternalKey, Entries[InternalIndex].Key))
                    {
                        return true;
                    }

                    return false;
                }

                public void Reset()
                {
                    InternalIndex = -1;
                }
            }
        }

        private sealed class ComparerSort : IComparer<Entity>
        {
            private readonly IComparer<KeyValuePair<TKey, TValue>> Comparer;

            public ComparerSort(IComparer<KeyValuePair<TKey, TValue>> Comparer)
            {
                this.Comparer = Comparer;
            }

            public int Compare(Entity x, Entity y)
            {
                return Comparer.Compare(
                    new KeyValuePair<TKey, TValue>(x.Key, x.Value),
                    new KeyValuePair<TKey, TValue>(y.Key, y.Value));
            }
        }

        private sealed class ComparisonSort : IComparer<Entity>
        {
            private readonly Comparison<KeyValuePair<TKey, TValue>> Comparer;

            public ComparisonSort(Comparison<KeyValuePair<TKey, TValue>> Comparer)
            {
                this.Comparer = Comparer;
            }

            public int Compare(Entity x, Entity y)
            {
                return Comparer(
                    new KeyValuePair<TKey, TValue>(x.Key, x.Value),
                    new KeyValuePair<TKey, TValue>(y.Key, y.Value));
            }
        }

        /// <summary>
        /// 参数字典迭代器
        /// </summary>
        private sealed class Enumerator : IEnumerator<KeyValuePair<TKey, TValue>>, IDictionaryEnumerator
        {
            private readonly ParamsDictionary<TKey, TValue> InternalContent;
            private int InternalIndex;
            private int InternalNumber;

            public Enumerator(ParamsDictionary<TKey, TValue> Content)
            {
                InternalContent = Content;

                InternalNumber = 0;
                InternalIndex = -1;
            }

            public KeyValuePair<TKey, TValue> Current
            {
                get
                {
                    return new KeyValuePair<TKey, TValue>(InternalContent.InternalEntries[InternalIndex].Key, InternalContent.InternalEntries[InternalIndex].Value);
                }
            }

            public void Dispose() { }

            object IEnumerator.Current
            {
                get
                {
                    return Current;
                }
            }

            object IDictionaryEnumerator.Key
            {
                get
                {
                    return InternalContent.InternalEntries[InternalIndex].Key;
                }
            }

            object IDictionaryEnumerator.Value
            {
                get
                {
                    return InternalContent.InternalEntries[InternalIndex].Value;
                }
            }

            DictionaryEntry IDictionaryEnumerator.Entry
            {
                get
                {
                    return new DictionaryEntry(InternalContent.InternalEntries[InternalIndex].Key, InternalContent.InternalEntries[InternalIndex].Value);
                }
            }

            public bool MoveNext()
            {
                ++InternalIndex;

                while (InternalNumber < InternalContent.InternalCount)
                {
                    switch (InternalContent.InternalEntries[InternalIndex].HashCode)
                    {
                        case UnUsedHashCode:
                            return false;
                        case FreedHashCode:
                            ++InternalIndex;
                            break;
                        default:
                            ++InternalNumber;
                            return true;
                    }
                }

                return false;
            }

            public void Reset()
            {
                InternalNumber = 0;
                InternalIndex = -1;
            }
        }
    }
}